﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace Ymatou.ServiceCenter.Common.Extensions
{
    public static class MemoryCacheExtensions
    {
        public static void Set(this ObjectCache cache, string key, object value, int cacheSeconds)
        {
            if (value == null)
                return;
            DateTime absoluteExpiration = cacheSeconds <= 0 ? DateTime.MaxValue : DateTime.UtcNow.AddSeconds(cacheSeconds);
            CacheItemPolicy cacheItemPolicy = new CacheItemPolicy { AbsoluteExpiration = absoluteExpiration };
            cache.Set(key, value, cacheItemPolicy);
        }

        public static void Add(this ObjectCache cache, string key, object value, int cacheSeconds)
        {
            if (value == null)
                return;
            DateTime absoluteExpiration = cacheSeconds <= 0 ? DateTime.MaxValue : DateTime.UtcNow.AddSeconds(cacheSeconds);
            CacheItemPolicy cacheItemPolicy = new CacheItemPolicy { AbsoluteExpiration = absoluteExpiration };
            cache.Add(key, value, cacheItemPolicy);
        }


        public static object AddOrGetExisting(this ObjectCache cache, string key, object value, int cacheSeconds)
        {
            if (value == null)
                return null;
            DateTime absoluteExpiration = cacheSeconds <= 0 ? DateTime.MaxValue : DateTime.UtcNow.AddSeconds(cacheSeconds);
            CacheItemPolicy cacheItemPolicy = new CacheItemPolicy { AbsoluteExpiration = absoluteExpiration };
            return cache.AddOrGetExisting(key, value, cacheItemPolicy);
        }

        public static T Get<T>(this ObjectCache cache, string key)
        {
            object value = cache.Get(key);
            if (value == null)
                return default(T);

            if (value is T)
            {
                return (T)value;
            }

            return default(T);
        }

        public static T Get<T>(this ObjectCache cache, string key, TimeSpan? timeSpan, Func<T> getValue, bool cacheNullVaule = false)
        {
            DateTime absoluteExpiration = timeSpan == null ? DateTime.MaxValue : DateTime.Now.Add(timeSpan.Value);
            CacheItemPolicy cacheItemPolicy = new CacheItemPolicy { AbsoluteExpiration = absoluteExpiration };
            var value = cache.Get(key);
            if (cacheNullVaule == true && value != null && value is NullValue)
                return default(T);

            if (value != null && value is T) return (T)value;
            value = getValue();
            if (value == null)
            {
                if (cacheNullVaule == true)
                {
                    cache.Set(key, new NullValue(), cacheItemPolicy);
                }
            }
            else
            {
                cache.Set(key, value, cacheItemPolicy);
            }
            return (T)value;
        }
    }

    public class NullValue
    {
    }
}
